/*
 * image.cpp
 *
 *  Created on: 21-oct-2008
 *      Author: axel
 */

#include "imagen.h"

void Imagen::init(const QImage& im, const QString& titulo){
	imagen = QImage(im);
	filename = titulo;
	initGraphics();
	actualizar();
}

Imagen::Imagen(int w, int h): QGraphicsView(), imagen(w, h, QImage::Format_RGB32){
	initGraphics();
	actualizar();
}

Imagen::Imagen(const QImage& im) :
	QGraphicsView() {
	init(im, QString::fromUtf8("Sin Título"));
}

Imagen::Imagen(const QImage* im) :
	QGraphicsView() {
	init(*im, QString::fromUtf8("Sin Título"));
}

Imagen::Imagen(const QImage& im, const QString& titulo):QGraphicsView(){
	init(im, titulo);
}

Imagen::Imagen(const QImage* im, const QString& titulo):QGraphicsView(){
	init(*im, titulo);
}

Imagen::Imagen(const Imagen& im) :
	QGraphicsView() {
	init(im.getImagen(), im.getTitle());
}

Imagen::Imagen(const Imagen& im, const QString& titulo) :
	QGraphicsView() {
	init(im.getImagen(), titulo);
}

//Constructor desde archivo TFE
Imagen::Imagen(QWidget * parent, const QString& fileName) :
	QGraphicsView(parent) {
	filename = fileName;
	if (!filename.isEmpty()) {
		//Intentamos abrirlo como si fuera un tipo de imágenes standard
		imagen = QImage(filename);
		imagen = imagen.convertToFormat(QImage::Format_ARGB32);

		if (!imagen.isNull()) {
		} else if (filename.endsWith(".tfe", Qt::CaseInsensitive)) {
			//Se trata de una imagen TFE
			QFile file(filename);
			//Comprueba que se pueda abrir el archivo
			if (!file.open(QIODevice::ReadOnly)) {
				throw QString("No se puede abrir el fichero %1").arg(filename);
			} else {
				//Imagenes de 320x200
				imagen = QImage(320, 200, QImage::Format_RGB32);
				char c;
				int i = 0;
				int j = 0;

				//Recorre el fichero y añade a la imagen
				while (!file.atEnd()) {
					if (j == 320) {
						i++;
						j = 0;
					}
					file.getChar(&c);
					QRgb valor = qRgb((int) c, (int) c, int(c));

					imagen.setPixel(j, i, valor);
					j++;
				}

			}
		} else {
			throw QString::fromUtf8("Formato de archivo no válido");
		}

		//Configura el pixmap y el rubberband
		initGraphics();
		actualizar();
	} else {
		throw QString::fromUtf8("Nombre de fichero inválido");
	}
}

void Imagen::setTitle(const QString& titulo){
	filename = titulo;
}

void Imagen::initGraphics() {
	scene = new QGraphicsScene();
	linea = NULL;
	pixMap = NULL;

	//Perfil
	perfilActivo = false;

	//RubberBand
	rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
	setMouseTracking(true);
	rubberBandding = false;
	moviendoLinea = false;
}

void Imagen::actualizar() {
	makeHistograma();
	//Habría que configurar por si ya hay un pixmap activo, pues borrarlo
	if(pixMap != NULL){
		scene->removeItem(pixMap);
	}

	pixMap = scene->addPixmap(QPixmap::fromImage(imagen));
	this->setScene(scene);
}

void Imagen::backup() {
	if (!imagen.isNull()) {
		imagenBack = QImage(imagen);
	}
}

void Imagen::undo() {
	if (!imagenBack.isNull()) {
		setStatusTip("deshaciendo");
		imagen = QImage(imagenBack);
		actualizar();
	}
}

Imagen::~Imagen() {
}

void Imagen::setFilename(const QString nombre) {
	filename = nombre;
}

void Imagen::mousePressEvent(QMouseEvent *event) {
	//Comprueba si estamos haciendo el perfil para trazar la linea
	if (perfilActivo) {
		//Si no se esta moviendo empieza a pintar la linea
		if (!moviendoLinea) {
			origenF = mapToScene(event->pos());
			if (origenF.x() >= 0 && origenF.y() >= 0 && origenF.x()
					< imagen.width() && origenF.y() < imagen.height()) {
				//Si ya hay una linea la elimina
				if (linea != NULL) {
					scene->removeItem(linea);
					delete linea;
				}

				moviendoLinea = true;
				linea = scene->addLine(QLineF(origenF, origenF), QPen(
						Qt::green, 1, Qt::SolidLine, Qt::RoundCap,
						Qt::RoundJoin));
				linea->setZValue(1.0);
			}
		} else {
			destinoF = mapToScene(event->pos());
			//Si se estaba moviendo quiere decir que termino
			if (destinoF.x() >= 0 && destinoF.y() >= 0 && destinoF.x()
					< imagen.width() && destinoF.y() < imagen.height()) {
				moviendoLinea = false;
				lanzarFinLinea();
			}
		}
	} else {
		origen = event->pos();
		//Si no está haciendo el perfil esta seleccionando normalmente un área
		rubberBand->setGeometry(QRect(origen, QSize()));
		rubberBand->show();
		rubberBandding = true;
	}
}

void Imagen::mouseMoveEvent(QMouseEvent *event) {
	if (perfilActivo) {
		if (moviendoLinea) {
			destinoF = mapToScene(event->pos());
			if (destinoF.x() >= 0 && destinoF.y() >= 0 && destinoF.x()
					< imagen.width() && destinoF.y() < imagen.height()) {
				linea->setLine(QLineF(origenF, destinoF));
				scene->update(QRectF(origenF, destinoF));
			}
		}
	} else {
		if (rubberBandding) {
			rubberBand->setGeometry(QRect(origen, event->pos()).normalized());
		}
	}

	QPointF punto = mapToScene(event->pos());
	if(punto.x() >= 0 && punto.y() >= 0 && punto.x() < imagen.width() && punto.y() < imagen.height()){
		QPoint puntoI = QPoint(qRound(punto.x()), qRound(punto.y()));
		//emit movido(puntoI);
		mouseMove(puntoI, imagen.pixel(puntoI));
	}
}

void Imagen::mouseReleaseEvent(QMouseEvent *event) {
	rubberBandding = false;
	destino = event->pos();
}

QImage Imagen::subImagen() const {

	if (rubberBand->geometry().isEmpty()) {
		throw QString::fromUtf8("No hay área seleccionada");
	}

	QRect rubber = rubberBand->geometry();
	QPointF orig = mapToScene(rubber.topLeft());
	QPointF dest = mapToScene(rubber.bottomRight());
	QRectF seleccion = QRectF(orig, dest);
	seleccion = seleccion.intersect(QRectF(QPointF(0,0), imagen.size()));
	int xr = qRound(seleccion.x());
	int yr = qRound(seleccion.y());
	int wr = qRound(seleccion.width());
	int hr = qRound(seleccion.height());
	QRect selec = QRect(QPoint(xr, yr), QSize(wr, hr));
	return imagen.copy(selec);
}

void Imagen::save() {
	if (filename.isEmpty()) {
		filename = QDir::currentPath();
	}
	QString destino = QFileDialog::getSaveFileName(this, tr("Guardar"),
			filename, tr("Imagenes (*.png *.xpm *.jpg *.bmp *.tiff)"));
	if (!destino.isNull() && !imagen.save(destino)) {
		throw QString("No se pudo guardar la imagen");
	}
}

void Imagen::makeHistograma() {
	//Inicializa a cero
	for (int i = 0; i < MAXCOLOR; i++) {
		histograma[i] = 0;
	}

	//Recorre los pixeles de la imagen
	for (int i = 0; i < imagen.height(); i++) {
		for (int j = 0; j < imagen.width(); j++) {
			if (qRed(imagen.pixel(j, i)) == qBlue((imagen.pixel(j, i)))) {
				histograma[qRed(imagen.pixel(j, i))]++;
			}
		}
	}
}

int Imagen::ajustar(double d){
	int ret;
	ret = qRound(d);
	if (ret > 255) {
		ret = 255;
	} else if (ret < 0) {
		ret = 0;
	}
	return ret;
}

/*
 * Convierte a escala de grises especificando los pesos de cada componente
 * Por defecto convierte a RGB
 */
void Imagen::toGray(double r = 0.222, double g = 0.707, double b = 0.071) {
	//ntfs 0.299R 0.587G 0.114B
	//pal 0.222R 0.707G 0.071B
	backup();
	QRgb actual;
	int aux;
	for (int i = 0; i < imagen.height(); i++) {
		for (int j = 0; j < imagen.width(); j++) {
			actual = imagen.pixel(j, i);
			aux = ajustar(r * qRed(actual) + g * qGreen(actual) + b * qBlue(
					actual));
			imagen.setPixel(j, i, qRgb(aux, aux, aux));
		}
	}
	actualizar();
}

//Devuelve el ancho
int Imagen::getWidth() const {
	return imagen.width();
}

//Devuelve el alto
int Imagen::getHeight() const {
	return imagen.height();
}

//Calcula la media del brillo utilizando el histograma
void Imagen::getBrilloContraste(double & brillo, double & contraste) const {
	//Calculo del brillo
	brillo = 0;

	for (int i = 0; i < MAXCOLOR; i++) {
		brillo += i * histograma[i];
	}

	double total = getWidth() * getHeight();

	brillo /= total;

	//Calculo del contraste
	contraste = 0;
	double aux;
	for (int i = 0; i < MAXCOLOR; i++) {
		aux = (i - brillo);
		contraste += aux * aux * histograma[i];
	}
	contraste = sqrt(contraste / total);
}

//Calcula la entropia de la imagen
double Imagen::getEntropia() const {
	double res = 0;
	double total = getWidth() * getHeight();
	double p;

	double ln2 = log(2.0);

	for (int i = 0; i < MAXCOLOR; i++) {
		p = histograma[i] / total;

		if (p != 0) {
			double l = (log(p) / ln2);
			res += p * l;
		} else {
			res += 0;
		}

	}
	return -res;
}

void Imagen::getRangoDinamico(int & min, int & max) const {
	min = -1;
	for (int i = 0; i < MAXCOLOR && min == -1; i++) {
		if (histograma[i] > 0) {
			min = i;
		}
	}

	max = -1;
	for (int i = (MAXCOLOR -1); i >= 0 && max == -1; i--) {
		if (histograma[i] > 0) {
			max = i;
		}
	}
}

void Imagen::getHistogramaA(int * histogramaA) {
	int sum = 0;

	for (int i = 0; i < MAXCOLOR; i++) {
		sum += histograma[i];
		histogramaA[i] = sum;
	}
}

void Imagen::getHistogramaANorm(double * histogramaANorm) {
	int sum = 0;
	QSize qsize = imagen.size();
	int size = qsize.width() * qsize.height();
	for (int i = 0; i < MAXCOLOR; i++) {
		sum += histograma[i];
		histogramaANorm[i] = sum/double(size);
	}
}

QWidget* Imagen::pintarHistograma() {
	Graficas2D grafica(800, 500);
	return grafica.pintarHistograma(histograma, QwtText(QString("Pixels")),
			QwtText(QString("")));
}

QWidget* Imagen::pintarHistogramaA() {
	Graficas2D grafica(800, 500);
	int histogramaA [MAXCOLOR];
	getHistogramaA(histogramaA);
	return grafica.pintarHistograma(histogramaA,QwtText(QString("Pixels")), QwtText(QString("")));
}

Imagen Imagen::generarImagen(int * tabla) {
	QRgb actual;
	int aux;
	QImage nueva = imagen;
	for (int i = 0; i < nueva.height(); i++) {
		for (int j = 0; j < nueva.width(); j++) {
			actual = nueva.pixel(j, i);
			aux = ajustar(tabla[qRed(actual)]);
			nueva.setPixel(j, i, qRgb(aux, aux, aux));
		}
	}
	return Imagen(nueva);
}

QImage* Imagen::generarIma(const int* tabla) {
	QRgb actual;
	int aux;
	QImage* nueva = new QImage(imagen);
	for (int i = 0; i < nueva->height(); i++) {
		for (int j = 0; j < nueva->width(); j++) {
			actual = nueva->pixel(j, i);
			aux = ajustar(tabla[qRed(actual)]);
			nueva->setPixel(j, i, qRgb(aux, aux, aux));
		}
	}
	return nueva;
}

Imagen Imagen::ecualizar() {
	int tabla[MAXCOLOR];
	int histogramaA [MAXCOLOR];
	getHistogramaA(histogramaA);
	double M = 255;
	QSize qsize = imagen.size();
	int size = qsize.width() * qsize.height();
	for (int i = 0; i < MAXCOLOR; i++) {
		int aux = int((M / size) * histogramaA[i]) - 1;
		if (aux > 0) {
			tabla[i] = aux;
		} else {
			tabla[i] = 0;
		}
	}
	return Imagen(generarImagen(tabla));
}


QImage* Imagen::cuantizar(const int bits) {
	int tabla[MAXCOLOR];
	cout << bits << endl;
	int numColors = (1 << bits) - 1;
	//Número de veces que se repite el color
	int rep = (1 << (8 - bits));
	cout << "Número de colores " << numColors << endl;
	cout << "Número de repeticiones " << rep << endl;
	for (int color = 0; color < MAXCOLOR; color+=rep) {
		int limSup = color + rep;
		for (int j = color; j < limSup; j++) {
			tabla[j] = color;
		}

	}
	for (int i = 0; i < MAXCOLOR; i++) {
		cout << i << " " << tabla[i] << endl;
	}
	return generarIma(tabla);
}

QImage* Imagen::digitalizar(const int tam) {
	QImage* imaNew = new QImage(imagen);
	cout << "Estoy digitalizando " << tam << endl;
	int size = tam * tam;
	for (int y = 0; (y + tam) < imaNew->height(); y += tam) {
		for (int x = 0; (x + tam) < imaNew->width(); x += tam) {
			int limX = x + tam;
			int limY = y + tam;
			int sum = 0;
			for (int x1 = x; x1 < limX; x1++) {
				for (int y1 = y; y1 < limY; y1++) {
					sum += qRed(imaNew->pixel(x1, y1));
				}
			}
			int aux = sum / size;
			for (int x1 = x; x1 < limX; x1++) {
				for (int y1 = y; y1 < limY; y1++) {
					imaNew->setPixel(x1, y1, qRgb(aux, aux, aux));
				}
			}
		}
	}
	return imaNew;
}

QImage* Imagen::transformacionLineal(QList<QLine> lineas) {
	int tabla[MAXCOLOR];
	QLine linea;
	if (!lineas.empty()) {
		linea = lineas.takeFirst();
		cout << linea.x2() << " " << linea.y2() << endl;
		cout << "dy " << linea.dy() << " dx " << linea.dx() << endl;
		double m = double(linea.dy()) / double(linea.dx());
		double n = double(linea.y1()) - m * double(linea.x1());
		cout << "m = " << m << " n = " << n << endl;
		for (int i = 0; i < MAXCOLOR; i++) {
			//En el caso de que no haya más líneas los valores se dejan igual;
			if (linea.x2() > i && i >= linea.x1()) {
				int aux = int(m * i + n);
				//cout << "aux " << aux << endl;
				if (aux > MAXCOLOR - 1) {
					tabla[i] = MAXCOLOR - 1;
				} else {
					tabla[i] = aux;
				}
			} else if (linea.x1() > i) {
				tabla[i] = i;
			} else {
				if (lineas.empty()) {
					tabla[i] = i;
				} else {
					linea = lineas.takeFirst();
					cout << linea.x2() << " " << linea.y2() << endl;
					cout << "dy " << linea.dy() << " dx " << linea.dx() << endl;
					m = double(linea.dy()) / double(linea.dx());
					n = double(linea.y1()) - m * double(linea.x1());
					cout << "m = " << m << " n = " << n << endl;
					int aux = int(m * i + n);
					if (aux > MAXCOLOR - 1) {
						tabla[i] = MAXCOLOR - 1;
					} else {
						tabla[i] = aux;
					}

				}
			}
		}
	}
	for (int i = 0; i < MAXCOLOR; i++) {
		cout << i << " " << tabla[i] << endl;
	}
	return generarIma(tabla);
}

void Imagen::func0(int * tabla) {
	//obtengo el tamaño de la imagen
	double aux = (255 / log(MAXCOLOR));
	for (int i = 0; i < MAXCOLOR; i++) {
		tabla[i] = int(log(1 + tabla[i])*aux);
		//cout << "i " << tabla[i] << endl;
	}
}

void Imagen::func2(int * tabla, const double k, const int* histogramaA) {
	QSize qsize = imagen.size();
	int size = qsize.width() * qsize.height();
	double aux1 = (255 / k);
	double aux2 =  exp(k)-1;
	for (int i = 0; i < MAXCOLOR; i++) {
		tabla[i] = int(aux1 * log(1 + aux2*histogramaA[i]/size));
		cout << "i " << tabla[i] << endl;
	}
}



void Imagen::func1(int *tabla, const double k) {
	double aux1 = (255 / k);
	double aux2 = exp(k)-1;
	for (int i = 0; i < MAXCOLOR; i++) {
		tabla[i] = qRound(aux1 * log(1 + aux2*(double(tabla[i])/255)));
	}
}



QImage* Imagen::logaritmo(const int numFunc, const double k) {
	//cout << k << numFunc << endl;
	int tabla[MAXCOLOR];
	for (int i = 0; i < MAXCOLOR; i++) {
		tabla[i] = i;
	}
	if (numFunc == 0) {
		func0(tabla);
	} else if (numFunc == 1) {
		func1(tabla,k);
	} else if (numFunc == 2) {
		int histogramaA [MAXCOLOR];
		getHistogramaA(histogramaA);
		func2(tabla,k, histogramaA);
	}
	return generarIma(tabla);
}

QImage* Imagen::exponencial(const int numFunc, const double k) {
	//cout << k << numFunc << endl;
	int tabla[MAXCOLOR];
	int tablaNeg[MAXCOLOR];
	//Tabla negada

	for (int i = 0; i < MAXCOLOR; i++) {
		tablaNeg[i] = MAXCOLOR -1 -i;
	}

	//Sustituyo en las fórmulas
	if (numFunc == 0) {
		func0(tablaNeg);
	} else if (numFunc == 1) {
		func1(tablaNeg,k);
	} else if (numFunc == 2) {
		int histogramaA [MAXCOLOR];
		getHistogramaA(histogramaA);
		int  aux [MAXCOLOR];
		for (int i = 0; i < MAXCOLOR; i++) {
			aux[i] = histogramaA[MAXCOLOR -1 -i];
		}
		func2(tablaNeg,k, aux);
	}

	for (int i = 0; i < MAXCOLOR; i++) {
		tabla[i] = MAXCOLOR -1 -tablaNeg[i];
	}

	return generarIma(tabla);
}

QImage* Imagen::espHisto(const double * histogramaANorm2) {
	int tabla[MAXCOLOR];
	double histogramaANorm [MAXCOLOR];
	getHistogramaANorm(histogramaANorm);
	//for (int i = 0; i < MAXCOLOR; i++) {
	//		cout << " i " << histogramaANorm[i] << endl;
	//}
	int pos = 0;
	for (int i = 0; i < MAXCOLOR; i++) {
		if (pos >= MAXCOLOR) {
			tabla[i] = (MAXCOLOR -1);
		} else {
			while (pos < MAXCOLOR) {
				if (histogramaANorm[i]< histogramaANorm2[pos]) {
					tabla[i] = pos;
					break;
				} else {
					pos++;
				}
			}
		}
	}
	for (int i = 0; i < MAXCOLOR; i++) {
		cout << " i " << tabla[i] << endl;
	}
	return generarIma(tabla);
}

QImage* Imagen::diferencia(const QImage& imagen2, const int dif) {
	QRgb actual;
	QRgb actual2;
	QImage* nueva = new QImage(imagen);
	for (int i = 0; i < nueva->height(); i++) {
		for (int j = 0; j < nueva->width(); j++) {
			actual = nueva->pixel(j, i);
			actual2 = imagen2.pixel(j, i);
			int res = abs(qRed(actual) - qRed(actual2));
			if (res > dif) {
				nueva->setPixel(j, i, qRgb(255, 0, 0));
			}
		}
	}
	return nueva;
}

QImage Imagen::getVecindad(int x, int y, int dist){
	int tam = 2*dist + 1;
	QRect seleccion(QPoint(x-dist, y-dist), QSize(tam, tam));
	seleccion = seleccion.intersect(QRect(QPoint(0,0), imagen.size()));
	return imagen.copy(seleccion);
}

QList <Punto> *Imagen::brasenham(const int x1, const int y1, const int x2, const int y2) {

	QList<Punto> *puntos = new QList<Punto>();
	int x=x1,y=y1,dx,dy,s1,s2;
	int i,dp,temp,swap=0;

	//cout << " x = " << x << " y = " << y << endl;
	puntos->push_back(Punto(x,y));
	dx=abs(x2-x1);
	dy=abs(y2-y1);

	if(x2<x1) s1=-1;
	else if(x2>x1) s1=1;
	else s1=0;

	if(y2<y1) s2=-1;
	else if(y2>y1) s2=1;
	else s2=0;

	dp=2*dy-dx;
	if(dy>dx) {
		temp=dx;
		dx=dy;
		dy=temp;
		swap=1;
	}
	for(i=1;i<=dx;i++) {
		if(dp<0) {
			if(swap){
				y = y + s2;
				puntos->push_back(Punto(x,y));
				//cout << " x = " << x << " y = " << y << endl;

			}
			else {
				x = x + s1;
				puntos->push_back(Punto(x,y));
				//cout << " x = " << x << " y = " << y << endl;

			}
			dp+=2*dy;
		}
		else {
			x = x+s1;
			y = y + s2;
			puntos->push_back(Punto(x,y));
			//cout << " x = " << x<< " y = " << y << endl;

			dp=dp+2*dy-2*dx;
		}
	}
	return puntos;
}

void Imagen::derivada(double * derivada, double * puntos, const int size) {
	derivada[0] = 0;
	for (int i = 1; i < size -1; i++) {
		derivada[i] = puntos[i] - puntos[i+1];
		//cout << derivada[i] << endl;
	}
}

void Imagen::suavizar(double * suavizado, double * puntos, const int size,  const int k) {

	for(int i = 0; i < size; i++) {
		int cont = 0;
		int limInferior =i - k;
		if (limInferior < 0) limInferior = 0;
		int limSuperior = i + k;
		if (limSuperior >= size) limSuperior = size -1;
		int sum = 0;
		for (int x = limInferior; x < i; x++ ) {
			sum += qRound(puntos[x]);
			cont++;
		}
		for (int x = i + 1; x <= limSuperior; x++ ) {
			sum += qRound(puntos[x]);
			cont++;
		}
		suavizado[i] = sum /cont;
	}
}

void Imagen::perfil(QWidget ** graficas, const int x1, const int y1, const int x2, const int y2) {
	//Obtengo los píxeles que forman la líneas
	cout << " x1 " << x1 << " y1 " << y1 << " x2 " << x2 << " y2 " << y2 << endl;
	QList <Punto> *puntos = brasenham(x1,y1,x2,y2);

	//Declaro variables
	QRgb actual;
	int size = puntos->size();
	double xs [size];
	double ys [size];
	//Veo que color es el de cada pixel
	for (int i = 0; i < size; i++) {
		Punto aux = puntos->takeFirst();
		actual = imagen.pixel(int(aux.getX()), int(aux.getY()));
		xs[i] = double(i);
		ys[i] = double(qRed(actual));
	}

	//Pinto la gráfica
	Graficas2D grafica(400, 400);

	graficas[0] = grafica.pintarGraficaXY(size, xs, QwtText(QString("Pixels")), ys, QwtText(QString("Color")), QwtText(QString("Perfil")));

	double dys [size];
	derivada(dys, ys, size);
	graficas[1] = grafica.pintarGraficaXY(size, xs, QwtText(QString("Pixels")), dys, QwtText(QString("Color")), QwtText(QString("Derivada Perfil")));
	double sys [size];
	suavizar(sys, ys, size, 4);
	graficas[2] = grafica.pintarGraficaXY(size, xs, QwtText(QString("Pixels")), sys, QwtText(QString("Color")), QwtText(QString("Suavizado Perfil")));
	double dsys [size];
	derivada(dsys, sys, size);
	graficas[3] = grafica.pintarGraficaXY(size, xs, QwtText(QString("Pixels")), dsys, QwtText(QString("Color")), QwtText(QString("Derivada Suavizado Perfil")));
}

void Imagen::mouseMove(QPoint punto, QRgb color){
	emit movido(punto, color);
}

void Imagen::setPerfil(bool valor){
	perfilActivo = valor;
	if(!perfilActivo && linea != NULL){
		scene->removeItem(linea);
	}
}

QPoint Imagen::pointf2point(const QPointF& punto){
	return QPoint(qRound(punto.x()), qRound(punto.y()));
}

void Imagen::lanzarFinLinea(){
	emit finLinea(pointf2point(origenF), pointf2point(destinoF));
}

void Imagen::actualizarBrilloContraste(double m, double n){
	int tabla[MAXCOLOR];

	for (int i = 0; i < MAXCOLOR; i++) {
		tabla[i] = int(m * i + n);
	}
	modificarImagen(tabla);
}

void Imagen::modificarImagen(int tabla[MAXCOLOR]){
	QRgb actual;
	int aux;

	if(imagenBack.isNull()){
		backup();
	};

	for (int i = 0; i < imagen.height(); i++) {
		for (int j = 0; j < imagen.width(); j++) {
			actual = imagenBack.pixel(j, i);
			aux = ajustar(tabla[qRed(actual)]);
			imagen.setPixel(j, i, qRgb(aux, aux, aux));
		}
	}

	actualizar();
}


QImage* Imagen::negativo() {
	int tabla[MAXCOLOR];
	int x = MAXCOLOR -1;
	for (int i = 0; i < MAXCOLOR; i++) {
		tabla[i] = x;
		x--;
	}
	return generarIma(tabla);
}

void Imagen::aplicarRuidoImpulsivo(double porcentaje, Imagen * qRuido) {
	QImage& imagen = getQImage();
	Ruido ruido(&imagen);
	ruido.impulsivo(porcentaje);
	ruido.aplicarRuido(&qRuido->getQImage());
	qRuido->actualizar();
	actualizar();
}

void Imagen::aplicarRuidoUniforme(double porcentaje, int n1, int n2, Imagen * qRuido) {
	QImage& imagen = getQImage();
	Ruido ruido(&imagen);
	ruido.uniforme(porcentaje,n1,n2);
	ruido.aplicarRuido(&qRuido->getQImage());
	qRuido->actualizar();
	actualizar();
}

void Imagen::aplicarRuidoGaussiano(double porcentaje, int n, Imagen * qRuido) {
	QImage& imagen = getQImage();
	Ruido ruido(&imagen);
	ruido.gaussiano(porcentaje,n);
	ruido.aplicarRuido(&qRuido->getQImage());
	qRuido->actualizar();
	actualizar();
}

void Imagen::aplicarFiltro(double *kernel, int kernelc, int kernelf, bool separable) {
	QImage& imagen = getQImage();
	Filtro filtro(&imagen, kernel, kernelc, kernelf, separable);
	filtro.aplicarFiltro();
	actualizar();
}

void Imagen::aplicarFiltroMediana(int f,int c){
	Filtro::vmMediana(getQImage(), f, c);
	actualizar();
}
void Imagen::aplicarFiltroModa(int f,int c){
	Filtro::vmModa(getQImage(), f, c);
	actualizar();
}
void Imagen::aplicarFiltroKVecinos(int f, int c, int k) {
	Filtro::vmKVecinos(getQImage(),f,c,k);
	actualizar();
}




